// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <map>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/base/order/product_info_cache.h"
#include "coin2/exchange/bybit_futures/symbology/currency.h"
#include "coin2/exchange/bybit_futures/symbology/product.h"

namespace coin2::exchange::bybit_futures::order_v3 {

class BybitFuturesParser : public base::order::BaseParser {
 public:
  const ParseResult& ParseRawMessage(const RawMessage& msg) override;
  AccountBalance ParseBalance(const JsonValue& doc) override;
  AccountPosition ParsePosition(const JsonValue& doc) override;
  bool ParseRawBalance(const JsonValue& doc, RawBalanceMap* raw_balance_map);
  bool ParseRawPosition(const JsonValue& doc, RawPositionMap* raw_position_map);

 private:
  void ParseSubmitResponse();
  void ParseCancelResponse();
  void ParseRestOrdersInfo();
  void ParseRestFillInfoList();
  void ParseRestAccountBalance();
  void ParseRestAccountPosition();
  void ParseWsMessage();

  auto ParseWsOrderInfoListV2(const JsonValue& data) -> ProductOrderBundle;
  auto ParseWsFillInfoListV2(const JsonValue& data) -> ProductFillBundle;
  auto ParseBalanceFromWs(const JsonValue& doc) -> AccountBalance;
  auto ParsePositionFromWs(const JsonValue& doc) -> AccountPosition;
  void ParseProductPosition(const JsonValue& data, AccountPosition* acc_position);
  bool ParseProductPositionV2(const JsonValue& data, RawPositionMap* raw_position_map);
  auto ParseRestOrderInfo(const JsonValue& data) -> coin::proto::ProductOrderElement;
  bool CompareLastBalance(const std::string& symbol, double total_balance, const JsonValue& doc);
  bool ParseHeader(
      const std::shared_ptr<AsioHttpContext>& http_context,
      std::string* rate_limit_info);

 private:
  // to handle position initialize
  std::string extra_info_;
  std::set<std::string> setlle_coin_cache_set_;
  RawPositionMap position_cache_map_;
  bool is_account_balance_initialized_ = false;
  bool is_account_position_initialized_ = false;
  bool ignorable_position_event_ = false;

  // to handle abnormal balance
  std::map<std::string, double> last_total_balance_;
  std::map<std::string, int64_t> abnormal_balance_;
};

}  // namespace coin2::exchange::bybit_futures::order_v3
